import { useMemo, type ReactNode } from "react";
import { GanttConsts } from "../../constants";
import { cn } from "../../helpers/utils";
import type { TaskMode } from "../../types";
import dayjs, { Dayjs } from "dayjs";
import { splitDateRange } from "../../helpers/time";
import { getTimeUnitWidth } from "../../helpers/utils";

interface TimeHeaderProps {
    tasksStart: Dayjs;
    tasksEnd: Dayjs;
    taskMode: TaskMode;
}

export default function TimeHeader({ tasksStart, tasksEnd, taskMode }: TimeHeaderProps) {
    return (
        <div className="flex flex-col">
            <Primary tasksStart={tasksStart} tasksEnd={tasksEnd} taskMode={taskMode} />
        </div>
    )
}

const getTimeHeaderSplitWidth = (taskMode: TaskMode, item: [string, string]) => {
    const timeUnitWidth = getTimeUnitWidth(taskMode);
    return taskMode === "Day"
        ? timeUnitWidth
        : (dayjs(item[1]).diff(dayjs(item[0]), "day") + 1) * timeUnitWidth;
}

const renderDayItem = (date: Dayjs, index: number, taskMode: TaskMode) => {
    const isWeekend = date.isoWeekday() === 6 || date.isoWeekday() === 7;
    return (
        <div
            key={`primary-day-${index}`}
            className={cn("w-full text-sm flex justify-center items-center shadow-lg", {
                "bg-orange-400 text-white": !isWeekend,
                "bg-orange-500": !isWeekend && index % 2 == 0,
                "bg-orange-100 text-orange-400": isWeekend,
            })}
            style={{
                width: `${getTimeUnitWidth(taskMode)}px`,
                height: `${GanttConsts.HEAD_HEIGHT}px`
            }}
        >
            {date.format("YYYY-MM-DD")}
        </div>
    );
};

const renderRangeItem = (item: [string, string], index: number, mode: TaskMode) => {
    let primaryText = "";
    switch (mode) {
        case "Week":
            primaryText = `${dayjs(item[0]).format("YYYY-MM-DD")} ~ ${dayjs(item[1]).format("YYYY-MM-DD")}`;
            break;
        case "Month":
        case "Quarter":
        case "Year":
            primaryText = `${dayjs(item[0]).format("YYYY-MM-DD")} ~ ${dayjs(item[1]).format("YYYY-MM-DD")}(${dayjs(item[1]).diff(item[0], "day") + 1}d)`;
            break;
    }

    return (
        <div
            key={`primary-${index}`}
            className={cn("w-full text-sm flex justify-center items-center shadow-lg", {
                "bg-orange-400 text-white": true,
                "bg-orange-500": index % 2 == 0,
            })}
            style={{
                width: `${getTimeHeaderSplitWidth(mode, item as [string, string])}px`,
                height: `${GanttConsts.HEAD_HEIGHT}px`
            }}
        >
            {primaryText}
        </div>
    );
};

const Primary = ({ tasksStart, tasksEnd, taskMode }: TimeHeaderProps) => {
    const primaryComponents = useMemo(() => {
        const components: ReactNode[] = [];
        const range = splitDateRange(tasksStart, tasksEnd, taskMode);

        if (taskMode === "Day") {
            const totalDays = tasksEnd.diff(tasksStart, 'day') + 1;
            const MAX_RENDER_DAYS = 365;

            if (totalDays > MAX_RENDER_DAYS) {
                components.push(
                    <div
                        key="day-limit-warning"
                        className="w-full text-sm flex justify-center items-center bg-red-400 text-white shadow-lg"
                        style={{
                            width: `${totalDays * getTimeUnitWidth(taskMode)}px`,
                            height: `${GanttConsts.HEAD_HEIGHT}px`
                        }}
                    >
                        时间范围过大 ({totalDays}天)，请缩小范围以提升性能
                    </div>
                );
            } else {
                let currentDayDate = tasksStart;
                let i = 0;
                while (currentDayDate <= tasksEnd) {
                    components.push(renderDayItem(currentDayDate, i, taskMode));
                    i++;
                    currentDayDate = currentDayDate.add(1, 'day');
                }
            }
        } else {
            range.forEach((item, index) => {
                components.push(renderRangeItem(item as [string, string], index, taskMode));
            });
        }

        return components;
    }, [tasksStart, tasksEnd, taskMode]);

    return <div className="flex flex-row">{primaryComponents}</div>;
}
